#!/bin/bash
#***************************************************************************
#*                                                                         *
#*         Check-Tool if acpi passive trip_points are supported            *
#*                                                                         *
#*            Copyright (C) 2006 SUSE Linux Products GmbH                  *
#*                                                                         *
#*             Author(s): Frank Seidel <fseidel@suse.de>                   *
#*		Modified by: Arjan van de Ven <arjan@linux.intel.com>      *
#*                          integration with the LFDK shell API            *
#*                                                                         *
#* This program is free software; you can redistribute it and/or modify it *
#* under the terms of the GNU General Public License as published by the   *
#* Free Software Foundation; either version 2 of the License, or (at you   *
#* option) any later version.                                              *
#*                                                                         *
#* This program is distributed in the hope that it will be useful, but     *
#* WITHOUT ANY WARRANTY; without even the implied warranty of              *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
#* General Public License for more details.                                *
#*                                                                         *
#* You should have received a copy of the GNU General Public License along *
#* with this program; if not, write to the Free Software Foundation, Inc., *
#* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA                  *
#*                                                                         *
#***************************************************************************/

export THERMALPATH="/proc/acpi/thermal_zone"
export THROTTLINGPATH="$(echo /proc/acpi/processor/* |head -n 1)/throttling"
export CPUFREQPATH="$(echo /sys/devices/system/cpu/* |head -n 1)/cpufreq"
export OUTPUTTYPE="d"

function printhelp ()
{
	cat <<-EOHELP
	This script tries to determine if the passive trip point (given by
	the acpi interace in /proc) does work as expected.
	Following options can be given: 

	-h		This help you are looking at
	-s		Show only names of supported thermal_zones
	-u		Show only names of un-supported thermal_zones
	-d		Debug output (default)
EOHELP
}


#eval given opts

while getopts "hsud" optchar
do
	case "$optchar" in
		h)
			printhelp
			exit 0
			;;
		s)
			export OUTPUTTYPE="s"
			;;
		u)
			export OUTPUTTYPE="u"
			;;
		d)
			export OUTPUTTYPE="d"
			;;
		*)
			echo "Unknown option" >&2
			printhelp 
			exit 1
			;;
	esac
done


start_test thermal_trip "ACPI passive thermal trip points" \
"This test determines if the passive trip point works as expected."

#Go through zones
for ZONE in $THERMALPATH/*
do
	#check if passive trip point is shown at all

	if (grep passive "$ZONE/trip_points" &>/dev/null )
	then
		#save current temps
		CUR_PASSIVE="$(grep passive $ZONE/trip_points |sed -e 's/passive:[^0-9]*\([0-9]*\) C.*/\1/')"
		#critical trip point
		if (grep critical "$ZONE/trip_points" &>/dev/null)
		then
			export CUR_CRITICAL="$(grep critical $ZONE/trip_points |sed -e 's/critical (S5):[^0-9]*\([0-9]*\) C.*/\1/')"
		else
			export CUR_CRITICAL="0"
		fi
		#hot trip point
		if (grep "^hot" "$ZONE/trip_points" &>/dev/null	)
		then
			export CUR_HOT="$(grep '^hot' $ZONE/trip_points |sed -e 's/hot[^\:]*:[^0-9]*\([0-9]*\) C.*/\1/')"
		else
			export CUR_HOT="0"
		fi
		#active trip points
		if (grep "^active" "$ZONE/trip_points" &>/dev/null)
		then
			export CUR_ACTIVES="$(grep '^active' $ZONE/trip_points | sed -e 's/active[^\:]*:[^0-9]*\([0-9]*\) C.*/\1/' | tr '\n' ':')0"
		else
			export CUR_ACTIVES="0:0"
		fi

		

		#look for current throttling on first cpu
		CUR_THROT="$(grep active $THROTTLINGPATH |sed 's/active[^T]*T\([0-9]*\)/\1/')"

		#look for current cpufreq state
		if [ -d "$CPUFREQPATH" ]
		then
			#..and start stressing cpu to to see wheather it gets scaled down
			exec 2>/dev/null
			cat /dev/zero >/dev/null &
			export STRESSPID=$!

			sleep 3
			
			#cpu should be stressed now and current freq high
			export CUR_CPUFREQ="$( <$CPUFREQPATH/scaling_cur_freq)"
		fi

		#look for current polling frequency
		CUR_POLLING="$(sed -e 's/polling[^0-9]*\([0-9]*\) sec.*/\1/' $ZONE/polling_frequency)"

		#set new trip points
		echo "$CUR_CRITICAL:$CUR_HOT:20:$CUR_ACTIVES" > $ZONE/trip_points
		#mess current polling to get kernels attention
		echo 1 >$ZONE/polling_frequency
		echo 2 >$ZONE/polling_frequency
		echo $CUR_POLLING >$ZONE/polling_frequency &> /dev/null

		#give the kernel some time
		sleep 4

		#recheck throttling now
		NEW_THROT="$(grep active $THROTTLINGPATH |sed 's/active[^T]*T\([0-9]*\)/\1/')"
		#recheck cpufreq now
		if [ -d "$CPUFREQPATH" ]
		then
			export NEW_CPUFREQ="$( <$CPUFREQPATH/scaling_cur_freq)"

			#and stop stressing cpu
			kill $STRESSPID
			set -m
		fi

		#check for difference
		if ( [ "$NEW_THROT" -gt "$CUR_THROT" ] || [ "$NEW_CPUFREQ" -lt "$CUR_CPUFREQ" ] )
		then
			#yes, throttling is effective
			case "$OUTPUTTYPE" in
				d)
					if [ -n "$NEW_CPUFREQ" ]
					then
						report_result thermal_trip PASS "Zone ${ZONE##*/} supports passive trip point (throttled from T$CUR_THROT to T$NEW_THROT / cpufreq scaling from $CUR_CPUFREQ to $NEW_CPUFREQ kHz)."
					else
						report_result thermal_trip PASS "Zone ${ZONE##*/} supports passive trip point (throttled from T$CUR_THROT to T$NEW_THROT)."
					fi
					;;
				s)
					echo "${ZONE##*/}"
					;;
				u) 	;;
				*)
					echo "Internal error: unknown OUTPUTTYPE $OUTPUTTYPE." >&2
					exit 1
					;;
			esac
		else
			#no, throttling is not effective
			case "$OUTPUTTYPE" in
				d)
					report_result thermal_trip FAIL "Changing passive trip point seems uneffective in Zone ${ZONE##*/}."
					;;
				u)
					echo "${ZONE##*/}"
					;;
				s)	;;
				*)
					echo "Internal error: unknown OUTPUTTYPE $OUTPUTTYPE." >&2
                                        exit 1
                                        ;;
			esac
		fi

		#restor old values
		echo "$CUR_CRITICAL:$CUR_HOT:$CUR_PASSIVE:$CUR_ACTIVES" >$ZONE/trip_points
		echo 1 >$ZONE/polling_frequency
                echo 2 >$ZONE/polling_frequency
                echo $CUR_POLLING >$ZONE/polling_frequency &> /dev/null
		sleep 4

	else
		#cannot check as passive trip points are not supported
		case "$OUTPUTTYPE" in
			d)
				report_result thermal_trip WARN "Zone ${ZONE##*/} doesn't support passive trip point at all." 
				;;
			u)
				echo "${ZONE##*/}"
				;;
			s)	;;
			*)
				echo "Internal error: unknown OUTPUTTYPE $OUTPUTTYPE." >&2
				exit 1
				;;
		esac
	fi


done

finish_test thermal_trip
